evinben
Goto Top

SID des angemeldeten Benutzers auslesen und in Variable (in Batch) setzen.

SID per Batch auslesen

Hallo,

ich versuche SID des angemeldeten Benutzers in Batch auszulesen und in einer Variable zu setzen, damit ich mit dieser den Pfad zum Papierkorb
Laufwerk:\$Recycle.Bin\S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxx
ergänzen kann und generell für andere Zwecke in der Zukunft. Ich habe zwar ein VB-Skript, welches mit alle SID anzeigt bzw. anhand der angegebenen SID den Benutzernamen, allerdings sollte die Ausgabe in Batch sein.

Wäre es möglich die SID direkt mit Batch auszulesen oder nur über Umwege mit VBS? Das Letzere wäre natürlich auch eine vollständige und akzeptable Lösung.

Vielen Dank euch.

Gruß
evinben

Content-Key: 187921

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

Printed on: April 19, 2024 at 17:04 o'clock

Member: DerWoWusste
DerWoWusste Jul 12, 2012 at 12:11:10 (UTC)
Goto Top
Moin.

Ich kenne in Batch nur das Kommandozeilentool user2sid hierfür.
http://evgenii.rudnyi.ru/soft/sid/sid.txt
Kompilierte Versionen gibt es merkwürdigerweise vom Autor nicht mehr, aber Google findet einige.
Member: ColdZero89
ColdZero89 Jul 12, 2012 updated at 12:21:51 (UTC)
Goto Top
Moin,

wenn du ein VBS hast das dir die SID ausließt, lass das VBS doch in Batch entstehen und von Batch ausführen, so kannst du dann die allgemeinen Variablen in batch und in VBS nutzen und die ausgabe der SIDs dann in eine TXT datei o.ä. schreiben lassen.

Gruß Zero

P.S.: Poste dein VBS doch mal hier, dann kann ich mein gelerntes Wissen (durch bastla haha) auch mal nutzen ;)

Ich nutze diese Variante ja selbst in einigen Batches wie du in meinen schon gestellten Fragen sicherlich siehst.
Member: bastla
bastla Jul 12, 2012 at 12:50:03 (UTC)
Goto Top
@dww
Es gibt ja fast nix, was es bei SysInternals nicht gibt ... face-wink

Grüße
bastla
Member: bastla
bastla Jul 12, 2012 at 12:52:49 (UTC)
Goto Top
@ColdZero89
... wobei es ja kein Problem ist, auch ein VBScript aus dem Batch aufzurufen und die (mit "WScript.Echo" erzeugte) Ausgabe zu übernehmen - schematisch etwa:
for /f "delims=" %%i in ('cscript //nologo "C:\Utils\GetSID.vbs"') do set "SID=%%i"
Grüße
bastla
Member: ColdZero89
ColdZero89 Jul 12, 2012 updated at 13:04:25 (UTC)
Goto Top
... wobei es ja kein Problem ist, auch ein VBScript aus dem Batch aufzurufen und die (mit "WScript.Echo" erzeugte)
Ausgabe zu übernehmen - schematisch etwa:

DAS wusste ich nun bisher nicht, dennoch finde ich die Variante "All in One" am ende schöner, somit kann man das script theoretisch hin und her schieben. (sofern Pfadangaben dann nicht absolut sind sondern relativ)

Aber so frisch ich mein wissen halt weiter auf ;P

Gruß Zero

P.S. was heißt eigentlich immer Delims? und ja die schöne Funktion For /? habe ich genutzt - kapier nur den kleinen satz wenig xD

"Gibt einen Satz von Trennzeichen an. Diese ersetzen die Standardtrennzeichen TAB und Leerzeichen."
HEIßT? was solls bewirken? ^^
Member: evinben
evinben Jul 12, 2012 updated at 13:03:46 (UTC)
Goto Top
Hallo DerWoWusste,

externe Tools gibt es sicherlich viel und fast bei Microsoft (PsGetSid von Sysinternals: http://technet.microsoft.com/de-de/sysinternals/bb897417.aspx).
Danke dennoch.
Die Variante von ColdZero89 werde ich bevorzugen, da der Batch auf mehreren PCs werkeln wird.


hallo ColdZero89,

und die ausgabe der SIDs dann in eine TXT datei o.ä. schreiben lassen.
OK. Dann werde ich den vbs-Schnipsel im Batch einbauen. Verratest du bitte wie die vb-Ausgabe in txt-Datei (in dem gleichen Arbeitsverzeichnis unbedingt) erfolgen soll?
(Im Batch wäre dies mir soweit klar: echo kukuk >tmp.txt)

Anbei ist der vbs-Schnipsel:
'This set it to the local Machine  
'	strComputer = "."  
'Use a Network Computer Name here or it IP Address to run on a Network Computer  
'	strComputer = "COMPUTER_NAME OR IP_ADDRESS_HERE"  


Option Explicit
 Dim ColItems, ObjItem, Sid, strComputer, Wmi
 strComputer = "."  
  Set Wmi = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")   
  Set ColItems = Wmi.ExecQuery("SELECT * FROM Win32_UserAccount",,48)   
   For Each ObjItem in ColItems 
        Sid = Sid & _
         "SID " & vbTab & objItem.SID & vbCrLf &_  
         "Name" & vbTab & objItem.Name & vbCrLf & vbCrLf  
   Next
  MsgBox Sid, 0 + 32, "Sid Values"  

dann kann ich mein gelerntes Wissen (durch bastla haha)
Kein haha ;). Der Man (oder die Frau?) hat echt viel Wissen.

Gruß
evinben
Member: ColdZero89
ColdZero89 Jul 12, 2012 updated at 13:24:53 (UTC)
Goto Top
Moin,

in die Batch baust du das sos ein
set "%S%=%temp%\SID_auslesen.vbs"  

> "%S%" echo 'This set it to the local Machine   
>> "%S%" echo '	strComputer = "."   
>> "%S%" echo 'Use a Network Computer Name here or it IP Address to run on a Network Computer   
>> "%S%" echo '	strComputer = "COMPUTER_NAME OR IP_ADDRESS_HERE"   
>> "%S%" echo Option Explicit   
>> "%S%" echo Dim ColItems, ObjItem, Sid, strComputer, Wmi   
>> "%S%" echo strComputer = "."   
>> "%S%" echo  Set Wmi = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")    
>> "%S%" echo  Set ColItems = Wmi.ExecQuery("SELECT * FROM Win32_UserAccount",,48)    
>> "%S%" echo   For Each ObjItem in ColItems    
>> "%S%" echo        Sid = Sid & _   
>> "%S%" echo         "SID " & vbTab & objItem.SID & vbCrLf &_   
>> "%S%" echo         "Name" & vbTab & objItem.Name & vbCrLf & vbCrLf   
>> "%S%" echo   Next   
>> "%S%" echo  MsgBox Sid, 0 + 32, "Sid Values"  

cscript //nologo "%S%"  
(ich hab ne böse vermutung da is mir irgendwo nen fehler unterlaufen und bastla rügt mich gleich face-big-smile)

Du musst nun nur noch die Ausgabe gegen Gesetzte Variable tauschen und diese dann, wie du es gesagt hast mit echo in eine Datei schreiben.

Die Variablen rufst du in VBS mit "%VARIABLE%" auf.

Ich hoffe soweit ist alles richtig mir im Kopf geblieben ^_^ ansonsten bastla? Berichtige mich wenn ich was falsches erzählt/geschrieben habe.

Gruß Zero

P.S.: Ja bastla is nen Genie! (Egal ob Mann oder Frau - Hut ab ^-^)
Member: bastla
bastla Jul 12, 2012 updated at 16:29:52 (UTC)
Goto Top
Hallo ColdZero89!

Rügen werde ich Dich sicher nicht, aber wenn die Ausgabe in den Batch (und / oder in eine Datei) soll, besser wie oben angesprochen "WScript.Echo" anstelle von "MsgBox" ...

... dann funktioniert nämlich zB auch
cscript //nologo "%S%">SID.txt
Für die Weiterverarbeitung würde es sich aber anbieten, SID und Name ohne zusätzliche Angaben in einer Zeile auszugeben, etwa:
WScript.Echo objItem.SID & vbTab & objItem.Name
wobei das Trennzeichen natürlich kein TAB sein muss ...
Übrigens zu "for" und "delims": Es gibt hier doch ein so schönes Tutorial zur FOR-Schleife ...

Grüße
bastla

P.S.: Bin keine "bastlarine", nehme die Blumen aber trotzdem gerne an ... face-smile
Member: rubberman
rubberman Jul 12, 2012 at 21:37:30 (UTC)
Goto Top
Hallo Zusammen!

@evinben

Falls dir WMIC zur Verfügung steht, wäre auch dies möglich:
@echo off &setlocal
for /f %%i in ('WMIC USERACCOUNT Where "Name='%username%'" Get SID /value') do (  
  for /f %%j in ("%%i") do set "%%j"  
)

echo %SID%
pause

Grüße
rubberman
Member: ColdZero89
ColdZero89 Jul 13, 2012 updated at 09:02:42 (UTC)
Goto Top
Moin,

Ah gut dann war soviel nicht Falsch, nur wieder zu kurz gedacht das man einige befehle sich einfach sparen kann und zusammenpacken kann.

Gruß Zero

P.S.: ALso dann doch lieber Bier oder nen schöner Wein? (Weiß ja nicht in welchem Alter du bist) face-devilish
Member: evinben
evinben Jul 13, 2012, updated at Jul 22, 2012 at 20:01:40 (UTC)
Goto Top
Hallo ColdZero89,

danke dir für deine Bereitschaft mir zu helfen.
P.S. was heißt eigentlich immer Delims?...
delims kommt von Delimeter und heißt auf Deutsch Trennzeichen. Wenn du diesen Parameter weg lässt, dann ist das standardmäßige Trennzeichen in der FOR-Schleife das Leerzeichen (SPACE) und/oder das TAB-Zeichen. Wenn du allerding eine txt-Datei bearbeiten möchtest, in welcher folgendes auf einer Zeile steht
ColdZero89|Tel=123,Bastla|Tel=007,evinben|Tel=noch kein
und du möchtest alle Kontakte voneinander trennen (also die Tokens in Variablen abfangen) dann benutzst du gerne den Parameter delims, z. B. so:
for /f „delims=,“ %%d in (KontakteKommagetrennt.csv) do echo %%d &echo %%d>>KontakteUntereinander.txt
Hoffe es ist dir nun etwas verständlicher geworden. Der Beitrag von Friemler ist einfach spitze, den habe ich mehrmals gelesen und kann nur weiter empfehlen.

Hallo bastla,

bin keine "bastlarine",…
Das klingt ja gar nicht schlecht. Der Tipp mit der VB-Ausgabe wird sicherlich eine Anwendung bald finden.


Hallo rubberman,

ich wusste es doch, dass es mit WIMC gehen müsste und daher bin sehr froh für deinen Tipp!
Der Trick mit
for /f %%j in ("%%i") do set "%%j"  
und genauer hier mit set "%%j", um die bestehende Ausgabe SID= gleich als neuer Variablen-Name zu benutzen, ist sehr raffiniert.
Der Befehl Set erfordert normalerweise einen Namen vor dem Gleichheitszeichen, also wie folgt: set SID=%%j
(nur set "%%j" sah es für mich irgendwie auf dem ersten Blick falsch ausface-smile
Ich vermute, dass es nur daher mit der abgekürzten SET-Schreibweise geht, da in der WMIC-Ausgabe ein Gleichheitszeichen vorhanden ist. Stimmt es?

Vielen Dank euch allen!
Projekt abgeschlossen.

Gruß
evinben
Member: rubberman
rubberman Jul 13, 2012 at 16:31:15 (UTC)
Goto Top
Hallo evinben.

Die zweite FOR /F Schleife wäre für die meisten Verarbeitungen einer Befehlsausgabe so unnütz wie ein Kropf. Die Ausgabe von WMIC ist jedoch (abhängig von der Version) in Unicode. Daran verschluckt sich die CMD einmal kräftig und spuckt einen verunglückten Zeilenumbruch (<CR><CR><LF>) aus. Eine erneute Verwurstung dieser Ausgabe in der 2. Schleife beseitigt diesen Fehler.

Und ja, der Inhalt von %%j wird expandiert bevor der SET Befehl ausgeführt wird. Somit kommt das '=' im Wert zum Tragen.

Grüße
rubberman
Member: evinben
evinben Jul 14, 2012 at 09:18:17 (UTC)
Goto Top
Hallo rubberman,

Daran verschluckt sich die CMD einmal kräftig und spuckt einen verunglückten Zeilenumbruch (<CR><CR><LF>) aus. Eine erneute Verwurstung dieser Ausgabe in der 2. Schleife beseitigt diesen Fehler.

Es geht eigentlich, wenn anstatt delims=* nur der zweite Token mit tokens=2 verwendet wird face-wink
for /f "delims== tokens=2" %%i in ('WMIC USERACCOUNT Where "Name='%UserName%'" Get SID /value') do (set SID=%%i)  
echo %SID%

Es gibt aber ein anderes größeres Problem. Diese Batch-Datei wird nur mit Administratorrechten ausgeführt (UAC erscheint, das Administrator-Konto wird gewählt und das Passwort eingegeben). Die Umgebungsvariable %UserName% läuft also unter fremdem Kontext, nämlich des Administrators. Nun ist die große Frage:
Wie kann der Namen des wahren „aktiven“ Benutzers ausgelesen werden? Nicht der Name irgendwelcher angemeldeten anderen Benutzer, da diese ja mehrere sein können, sondern von demjenigen, der die Batch-Datei ausführt?

Zur Not lasse ich momentan am allerersten den Benutzernamen ohne Administrator-Rechten in einer TEMP-Datei ausgeben (die später von der FOR-Schleife ausgelesen wird)
 if not exist tmp.txt echo %UserName% >tmp.txt
und nach der Eingabe des Passwortes wird der Batch erneut - diesmal mit Administrator-Rechten – ausgeführt und es läuft so weiter, so dass die korrekte SID ausgegeben wird.

Für jegliche Tipps, wie das Problem besser umgegangen werden könnte, wäre ich euch dankbar!

Gruß
evinben
Member: rubberman
rubberman Jul 14, 2012 updated at 11:43:19 (UTC)
Goto Top
Hallo evinben,

so ganz verstehe ich das nicht.
1. brauchst du dieses WMI Query nicht als Admin laufen zu lassen. UAC Prompt kommt auch nicht.
2. selbst wenn ich das Ding als Admin rennen lasse (mit meinem Account unter erhöhten Rechten), kommt immer noch die richtige Ausgabe.

Wenn du natürlich mit dem Adminaccount angemeldet bist (oder per RunAs) gibt es die SID des Admin Accounts. Was auch sonst?
Klar kannst du alle Accounts und die zugehörige SID als Liste bekommen, aber woher soll ein "dummes" Batchscript wissen, wer nun üblicherweise an dieser Kiste angemeldet ist? Wir haben in unserer Firma Rechner, an denen sitzen immer mal wieder andere Praktikanten. Unsere IT verpasst jedem von denen ihren eigenen Account. Mittlerweile sind da bestimmt 20 oder 30 Profile drauf... Wer ist denn da nun der User, den du benötigst? Kannst du irgend eine Regel definieren?

Grüße
rubberman
Member: evinben
evinben Jul 14, 2012 at 14:31:00 (UTC)
Goto Top
Hallo rubberman,

1. brauchst du dieses WMI Query nicht als Admin laufen zu lassen. UAC Prompt kommt auch nicht.
Das ist eine komplexere Batch-Datei, die nur mit Administratorrechten ausgeführt werden kann.
2. selbst wenn ich das Ding als Admin rennen lasse (mit meinem Account unter erhöhten Rechten), kommt immer noch die richtige Ausgabe.
Weil dein Benutzerkonto die Administratorrechte hat. Ausführung auf einem Benutzer ohne Administratorrechte erfordert nach UAC-Abfrage die Auswahl eines Benutzers mit erhöhten Rechten, unter welchem Kontext die Umgebungsvariablen eingelesen werden.

Wenn du natürlich mit dem Adminaccount angemeldet bist (oder per RunAs) gibt es die SID des Admin Accounts. Was auch sonst?
Die Benutzer sind nicht mit dem Administratorkonto angemeldet.

Klar kannst du alle Accounts und die zugehörige SID als Liste bekommen, aber woher soll ein "dummes" Batchscript wissen, wer nun üblicherweise an dieser Kiste angemeldet ist? Wir haben in unserer Firma Rechner, an denen sitzen immer mal wieder andere Praktikanten. Unsere IT verpasst jedem von denen ihren eigenen Account. Mittlerweile sind da bestimmt 20 oder 30 Profile drauf... Wer ist denn da nun der User, den du benötigst? Kannst du irgend eine Regel definieren?
Ja klar: derjenige Benutzer, der die Datei ausführt und das Passwort auf Vertrauen des Administrators eingibt.
Wie ich oben erwähnt habe, geht es auch mit der Ausgabe in eine txt-Datei. Da ich immer wieder lernen und alles wissen will, frage ich nach besseren Möglichkeiten nach und es klappt meistens - z. B. mit deiner Lösung mit WMIC.

Gruß
evinben
Member: rubberman
rubberman Jul 14, 2012 at 15:20:05 (UTC)
Goto Top
Hallo evinben.

Zitat von @evinben:
Ja klar: derjenige Benutzer, der die Datei ausführt
Das ist ja in dem Fall der Administratoraccount, denn ausgeführt wird die Datei erst nach UAC Prompt mit Passworteingabe.

Zitat von @evinben:
und das Passwort auf Vertrauen des Administrators eingibt.
Dann sollte der Admin soviel Vertrauen haben, und dem Benutzer gleich die nötigen Rechte einräumen. Das macht deutlich mehr Sinn, als sein Passwort weiter zu geben.

Grüße
rubberman
Member: evinben
evinben Jul 14, 2012 at 15:42:58 (UTC)
Goto Top
Hallo rubberman,

Dann sollte der Admin soviel Vertrauen haben, und dem Benutzer gleich die nötigen Rechte einräumen. Das macht deutlich mehr Sinn, als sein Passwort weiter zu geben.
Hier hast du wohl Recht. In der Praxis ist es öfter anders und da führt der Admin die Datei in der Schnelle selber aus.

OK, dann bleibt die Variante, wie es momentan ist - sie ist ebenso vollwertig.


Ein schönes Wochenende!

Gruß
evinben
Member: rubberman
rubberman Jul 14, 2012 updated at 20:22:16 (UTC)
Goto Top
Hallo evinben.

Irgend eine Möglichkeit findet sich immer face-wink
Einmal von hinten durch die Brust ins Knie:
@echo off &setlocal
if "%~1" == "" (  
  for /f %%i in ('WMIC USERACCOUNT Where "Name='%username%'" Get SID /value') do (  
    for /f %%j in ("%%i") do set "%%j"  
  )
  set "me=%~f0"  
  set "vbs=%temp%\uac.vbs"  
  setlocal EnableDelayedExpansion
    >"!vbs!" echo CreateObject^("Shell.Application"^).ShellExecute """!comspec!""", " /c ""!me!"" !SID!", "" , "runas", 1  
    call "!vbs!"  
    del "!vbs!"  
  endlocal
  goto :eof
)

echo SID: %1
pause
Ganz ohne temporäres VBScript geht's diesmal nicht. Starte per Doppelklick. Der UAC Prompt kommt später.
Dort wo momentan das echo SID: %1 steht kommt der Code den du als Admin ausführen willst.

Auch ein schönes WE!

rubberman
Member: evinben
evinben Jul 14, 2012 at 22:37:49 (UTC)
Goto Top
Hallo rubberman,

danke sehr. Mit ähnlicher Methode, über VB-Skript, werden die Bach-Dateien ausgeführt. Das temporäre VB-Skript sieht dann so aus:
CreateObject("Shell.Application").ShellExecute "D:\Projekte All User\Joint all files on current direction.bat","E:\Projekte 2012\Daten 07.2012.txt D:\Projekte All User\Daten 07.2012.txt",,"runas",1  
Allerdings schaffe ich immer noch nicht die übergebenen Argumente (hier im Beispiel beide Pfade zu den txt-Dateien) im Batch als zwei Argumente richtig zu empfangen, da diese nicht in Anführungszeichen stehen (ohne Anführungszeichen werden diese bedingt durch die vorhandenen Leezeichen in mehreren Argumenten zerlegt).

Etwas anders, was ich vor Kurzem heute festgestellt habe:
Alle Dateien, die in den erwähnten $Recycle.Bin-Ordner per Batch verschoben werden, werden nicht mehr für den Benutzer (mit der dazugehörigen SID) im Papierkorb im Windows Explorer angezeigt. Folgenderweise werden die Dateien in den Ordner $Recycle.Bin\%SID% verschoben:
move "%FullFileName%" "D:\$Recycle.Bin\S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxx"  
rem oder auf dem Laufwerk C:\
move "FullFileName%" "C:\$Recycle.Bin\S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxx"  
In der Eingabeaufforderung im Gegensatz werden alle diese Dateien mit dem DIR-Befehl wie folgt aufgelistet:
dir /s  "D:\$Recycle.Bin\S-1-5-21-xxxxxxxxxx-xxxxxxxxxx-xxxxxxxxxx-xxxx"  
pause >nul
angezeigt werden.

Woran könnte es liegen?

Gruß
evinben
Member: rubberman
rubberman Jul 14, 2012 at 23:07:44 (UTC)
Goto Top
Hallo evinben.

zum ersten:
CreateObject("Shell.Application").ShellExecute "D:\Projekte All User\Joint all files on current direction.bat","""E:\Projekte 2012\Daten 07.2012.txt"" ""D:\Projekte All User\Daten 07.2012.txt""",,"runas",1
In VBScript stehen Strings in Anführungszeichen eingeschlossen. Anführungszeichen innerhalb eines Strings müssen verdoppelt werden.
Willst du die umschließenden Anführungszeichen im Batch wieder entfernen, dann mit Tilde arbeiten (%~1 %~2).

zum zweiten:
So wie du denkst, liegen die Daten nicht im Papierkorb vor. Das Ding ist sicher ein Shellfolder und irgendwie virtualisiert. Ich müsste aber jetzt auch erst die Suchmaschine anwerfen ...

Grüße
rubberman
Member: rubberman
rubberman Jul 15, 2012 updated at 15:21:02 (UTC)
Goto Top
Hallo evinben.

Habe mal etwas gespielt. Also, ja, der Papierkorb ist ein Shellfolder. Mit den normalen Methoden des Filesystems kommst du nicht weit. Hier musst du dich auf VBS stützen, um mit Bordmitteln arbeiten zu können. Aber der Reihe nach ...

Auf meiner Kiste hier habe ich 2 Partitionen, C: und D:. Auf jeder Partition habe ich eine leere Textdatei erstellt und in den Papierkorb geschoben ("Neues Textdokument.TXT" auf C: und "Neues Textdokument_2.TXT" auf D: ).

Zunächst hab ich mir mal angesehen, was sich im Papierkorb befindet, und zwar mittels Batch seitens Filesystem:
*.bat
dir /a /s C:\$recycle.bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000
echo(&echo ------------------------------------------------------------------&echo(
dir /a /s D:\$recycle.bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000
Ausgabe:
 Datenträger in Laufwerk C: ist Acer
 Volumeseriennummer: 0XXX-XXXC

 Verzeichnis von C:\$recycle.bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000

16.07.2012  15:36    <DIR>          .
16.07.2012  15:36    <DIR>          ..
16.07.2012  15:36               544 $I9FHN32.TXT
16.07.2012  15:35                 0 $R9FHN32.TXT
13.04.2012  20:34               129 desktop.ini
               3 Datei(en),            673 Bytes

     Anzahl der angezeigten Dateien:
               3 Datei(en),            673 Bytes
               2 Verzeichnis(se), 215.856.205.824 Bytes frei

------------------------------------------------------------------

 Datenträger in Laufwerk D: ist Volume
 Volumeseriennummer: CXXX-XXX6

 Verzeichnis von D:\$recycle.bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000

16.07.2012  15:36    <DIR>          .
16.07.2012  15:36    <DIR>          ..
16.07.2012  15:36               544 $I36FXMR.TXT
16.07.2012  15:35                 0 $R36FXMR.TXT
13.04.2012  23:27               129 desktop.ini
               3 Datei(en),            673 Bytes

     Anzahl der angezeigten Dateien:
               3 Datei(en),            673 Bytes
               2 Verzeichnis(se), 38.474.506.240 Bytes frei
Weit und Breit nichts von den Originaldateinamen zu sehen. Dafür scheint es so dass je eine Datei beginnend mit $R existiert die die Originaldatei repräsentiert, sowie eine Datei beginnend mit $I die eine Binärdatei ist in der u. A. der ursprüngliche Pfad und Dateiname zu finden ist.
Somit sollte klar sein dass ein Verschieben einer Datei in den Papierkorb mittels Batch nicht funktionieren wird. Die Datei befindet sich dann zwar in diesem Verzeichnis, die Funktionen des Papierkorbs (angefangen bei der Anzeige im Explorerfenster, bis hin zu der Wiederherstellung der Datei) sind aber dafür nicht verfügbar.

Ergo - Shellfolder in VBScript austesten. Namespace 0x0A repräsentiert den Papierkorb des Benutzers:
*.vbs
Set oShApp = CreateObject("Shell.Application")  
Set oRecycler = oShApp.Namespace(&h0A)
Set colItems = oRecycler.Items()

For Each oItem in colItems
  txt = txt & oItem.Name & vbNewLine & oItem.Path & vbNewLine & vbNewLine
Next
WScript.Echo txt
Ausgabe:
Neues Textdokument_2.TXT
D:\$RECYCLE.BIN\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000\$R36FXMR.TXT

Neues Textdokument.TXT
C:\$Recycle.Bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000\$R9FHN32.TXT
Aha! Das sieht schon besser aus. Fehlt zwar die Beziehung zur $I Datei, aber egal.

Wir bekommen ja auch noch den gesamten Papierkorb (gesammelte Werke aus C: und D: ), also Probe auf's Exempel:
*.vbs
Set oShApp = CreateObject("Shell.Application")  
Set oRecycler = oShApp.Namespace("C:\$Recycle.Bin\S-1-5-21-4XXXXXXXXX-XXXXXXXXXX-XXXXXXXXX2-1000")  
Set colItems = oRecycler.Items()

For Each oItem in colItems
  txt = txt & oItem.Name & vbNewLine & oItem.Path & vbNewLine & vbNewLine
Next
WScript.Echo txt
Der Witz ist, dass ich trotzdem den Inhalt des gesamten Papierkorbs bekomme und nicht nur von C:. Warum? Ich hab keine Ahnung!

However. Du versuchst ja per Script eine Datei in den Papierkorb zu verschieben. Mit:
*.vbs
oRecycler.moveHere "C:\Pfad\Datei.ext"  
... hatte ich Erfolg. Siehe Folder.MoveHere method

Grüße
rubberman
Member: evinben
evinben Jul 16, 2012 at 10:34:25 (UTC)
Goto Top
Hallo rubbermann,

Der Witz ist, dass ich trotzdem den Inhalt des gesamten Papierkorbs bekomme und nicht nur von C:. Warum? Ich hab keine Ahnung!

Das ist normal. Und wie du es oben selbst schreibst: „Da der Papierkorb ein spezieller Ordner ist…“, zeigt dieser die Inhalte verknüpfter Recycle.Bin-Ordner aller Laufwerke an, allerdings aus Sicherheitsgründen nur diejenige, die von dem Benutzer persönlich gelöscht worden sind (derjenige Benutzer muss also angemeldet sein, um seine gelöschten Dateien sehen zu können).
Schaltest du den D:\-Laufwerk aus, so werden die Inhalte, die in diesem Laufwerk physikalisch verbleiben, nicht mehr im Papierkorb neben den anderen mit angezeigt.

oRecycler.moveHere "C:\Pfad\Datei.ext"
Du bist spitze!
Namespace 0x0A repräsentiert den Papierkorb des Benutzers:
Es würde mich brennend interessieren, wie du überhaupt auf die Idee gekommen bist Namespace 0x0A zu benutzen!

Projekt abgeschlossen

Schönen Gruß
evinben
Member: rubberman
rubberman Jul 16, 2012 at 12:06:04 (UTC)
Goto Top
Zitat von @evinben:
Es würde mich brennend interessieren, wie du überhaupt auf die Idee gekommen bist Namespace 0x0A zu benutzen!

Hallo evinben.

Steht alles geschrieben, man muss nur wissen wo face-wink
ShellSpecialFolderConstants enumeration

Grüße
rubberman
Member: evinben
evinben Jul 21, 2012, updated at Jul 24, 2012 at 04:51:43 (UTC)
Goto Top
Hallo rubberman,

wenn ich mit dem folgenden VB-Skript in einer Schleife alle Pfade der zu löschenden Dateien aus der temporär erstellen Text-Datei FullFileNames_tmp.txt zeilenweise einlese, werden leider keine Dateien gelöscht - der Befehl objRecycler.moveHere begleitend mit der Variable Zeile zeigt keine Reaktion.
Set objWShell = WScript.CreateObject("Wscript.Shell")  
Set objShellApp = CreateObject("Shell.Application")  
Set objRecycler = objShellApp.Namespace(&h0A)

'EingabePfad = "C:\Users\"  

'Bei Pfad mit Umgebungsvariable folgende Zeile benutzen  
EingabePfad = objWShell.ExpandEnvironmentStrings("%TMP%\")  

EingabeDatei = "FullFileNames_tmp.txt"  

Const ForReading = 1
Const ForWriting = 2

Set fso = CreateObject("Scripting.FileSystemObject") 'Objekt für Dateisystem erstellen  
Set objEingabe = fso.OpenTextFile(EingabePfad & EingabeDatei, ForReading)

Do Until objEingabe.AtEndOfStream
	Zeile = objEingabe.Readline
	msgbox Zeile	'Test: vollständigen Pfad zur Datei anzeigen, die gelöscht werden soll  
	objRecycler.moveHere Zeile
Loop

Schreibe ich allerdings nach objRecycler.moveHere anstatt der Variable "Zeile" den Pfad zu der Datei, die gelöscht werden soll:
objRecycler.moveHere "D:\Entwurf.txt"  
dann geht es.
Es ist echt frustrierend… da es keine Logik ergibt, warum es nicht funktionieren soll...

Aber auch außerhalb der DO-Schleife funktioniert moveHere mit der Variable "Zeile" nicht. Annbei der Abschnitt als Einzeiler, um allen Fehler aus dem Weg zu gehen:

CreateObject("Shell.Application").Namespace(&h0A).moveHere Zeile  

Gruß
evinben
Member: rubberman
rubberman Jul 22, 2012 updated at 15:23:01 (UTC)
Goto Top
Hallo evinben.

Dein Script funktioniert bei mir im Test ohne Probleme. Es liegt also die Vermutung nahe dass irgendwas mit dem Inhalt der Textdatei nicht stimmt. Ich gehe davon aus, dass dir deine Zeile 20 was ausspuckt? Falls nicht, hättest du es erwähnt, hoffe ich face-wink
Nun weiß ich nicht wie die Datei aussieht oder erzeugt wird. Darum kann ich dir erst mal nur Tipps geben, wie du die Ursache heraus bekommst.
1. Du könntest deine Zeile 20 mal wie folgt ändern:
	msgbox """" & Zeile & """"
Damit wird ersichtlich, ob du Leerzeichen am Zeilenende hast o.Ä.

2. Öffne die Datei in einem HEX Editor und schau dir an in welchem Zeichensatz der Inhalt vorliegt. Vielleicht liegt es daran dass die Datei im UTF-8 oder Unicode Format gespeichert ist.

3. Schreib mal eine Datei per Hand mit dem guten alten Notepad Editor. Achte beim Speichern auf das oben Genannte. (Keine Leerzeichen am Ende, Codierung ANSI)

Grüße
rubberman
Member: evinben
evinben Jul 24, 2012 at 05:55:31 (UTC)
Goto Top
Hallo rubberman,

noch zwei Stunden habe ich probiert das Skript in Bewegung zu bringen, dennoch zeigt die 21. Zeile immer noch keine Reaktion. Folgendes habe ich schrittweise versucht.
1. Den Inhalt des VB-Skriptes in einer neuen TXT-Datei kopiert und als ANSI abgespeichert.
2. Alle Leerzeichen, die am Ende jeder Zeile vorhanden waren, entfernt.
3. Die Datei auf einem anderen Computer ausgeführt
4. Die TXT-Datei, welche eingelesen wird, neuerstellt und einen Pfad zu einer Datei (die gelöscht bzw. korrekter ausgedruckt in den Papierkorb verschoben werden soll) in Anführungszeichen angegeben.

Es liegt also die Vermutung nahe dass irgendwas mit dem Inhalt der Textdatei nicht stimmt. Ich gehe davon aus, dass dir deine Zeile 20 was ausspuckt? Falls nicht, hättest du es erwähnt, hoffe ich face-wink
Doch, msgbox zeigt mir den Pfad vollständig an (also ohne Leerzeichen am Anfang und am Ende der Zeichenkette – auch zusätzlich mit msgbox """" & Zeile & """" geprüft).

Wie hast du es genauer bei dir getestet, als Einzeiler ohne Variable oder lasst du wie ich eine txt-Datei mit Pfade zu Dateien, welche in den Papierkorb verschoben werden sollen, einlesen und als Variable an objRecycler.moveHere übergeben? Das letztere funktioniert bei mir definitiv nicht.
Die Pfade bestehen nur aus lateinischen Buchstaben und ich glaube keine Sonderzeichen verwendet zu haben.

Für jeden weiteren Tipp wäre ich sehr dankbar!
Eventuell lässt sich das Skript irgendwie umstrukturieren?

Schade, dass ich keine Datei hier hochladen kann, ansonsten hätte ich einfach das Skript hier hochgeladen. Der Code oben wurde aus der VB-Datei ohne Zwischenveränderung 1:1 übernommen.

Gruß
evinben
Member: evinben
evinben Jul 24, 2012 updated at 06:41:05 (UTC)
Goto Top

back-to-topGESCHAFT!


Die Pfade in der txt-Datei, welche eingelesen wird, dürfen nicht in Anführungszeichen sein!
Seltsam, da wenn der Pfad in Anführungszeichen anstatt mit Variable direkt wie folgt eingegeben wird
objRecycler.moveHere "C:\user\Archiv_2010.txt"  
dann funktioniert es. Der Logik nach sollte es ebenso mit einer Variablen möglich sein. Aber leider nein und an der Stelle streitet VBS.

Ähhh, so viel Zeit verschwendet. Warum machen es die VB-Designer so? Wenn ich wüsste wie, dann würde ich denen gerne einen Verbesserungevorschlag abgeben.

rubberman@ vielen Dank noch mal beim Mitschwitzen.
Ich glaube also bei dir hat es mit der Variable ebenso nicht funktioniert.

Gruß
evinben
Member: rubberman
rubberman Jul 24, 2012 at 10:49:27 (UTC)
Goto Top
Zitat von @evinben:
Ich glaube also bei dir hat es mit der Variable ebenso nicht funktioniert.

Hallo evinben,

ich hatte keine umschließenden Anführungszeichen in meiner Testdatei. Hat tadellos funktioniert.

Die Anführungszeichen sind die Kennzeichnung für einen String im Quellcode, um einen String von eigentlichen Code (Variablen etc.) zu separieren. Sie sind letztlich nicht Bestandteil des Strings bei der Verabeitung der Zeichenfolge.

Grüße
rubberman
Member: evinben
evinben Jul 24, 2012 at 11:30:16 (UTC)
Goto Top
Sie sind letztlich nicht Bestandteil des Strings bei der Verabeitung der Zeichenfolge.

OK! Das sollte eine Lehre für mich sein. Im Batch nämlich wird die Zeichenkette (der String) problemlos mit den Anführungszeichen eingelesen und unbedingt als Bestandteil in die Variable gesetzt, das Verhalten ist also andersrum: wenn die Anführungszeichen in der Variable doch nicht benötigt werden, müssen diese etwa wie
set var=%var:"=%  
zuerst gefiltert werden (in der FOR-Schleife oder in dem IF-Befehl dann mit %~nx usw.).

Gut, andere Zeiten, andere Sprachen.

Danke für den Tipp!

Gruß
evinben