How to write STDOUT/STDIN via RedMon/cmd.exe to file? - redirect

I am trying to redirect a PS output to a file and process it further.
For this I am using the Printer Port Redirection RedMon which is sending the output to CMD.exe
C:\Windows\system32\cmd.exe
As arguments I expected that something like the following should work, but it does not. "%1" contains the user input for filename.
/c >"%1"
or
/c 1>"%1"
or
/c |"%1"
or
/c > "%1" 2>&1
What almost works if I send the output to a batch file which writes it then to file.
/c WriteOutput.bat "%1"
However, the batch file is somehow altering the file (skipping empty lines, and ignoring exclamation marks and so on...)
If possible I want to avoid a batch file. Is there a way to get it "directly" to a file?
Select "Print to FILE" in the printer options is not an option for me. I want the same end result but via cmd.exe being able to process it further.
Any ideas?
Edit:
Well, that's the batch file I used. It neglects empty lines and space at the beginning.
#echo off
setlocal
set FileName=%1
echo(>%FileName%.ps
for /F "tokens=*" %%A in ('more') do (
echo %%A>>%FileName%.ps
)

Well, so far I still haven't found a direct way to write STDIN via RedMon via CMD.exe to a file. As #aschipfl wrote, all the versions with for /F will skip lines and ignore certain characters.
However, with the following batch script (via RedMon) I end up with a "correct looking" file on disk.
C:\Windows\system32\cmd.exe /c WritePS.bat "%1"
"%1" contains the user input for filename without extension.
The Batch-File WritePS.bat looks as simple as this:
#echo off & setlocal
set FileName=%1.ps
more > "%FileName%"
However,
the resulting Postscript file is different from a file which I "Print to FILE" via the Postscript-Printer setup. I am pretty sure that all the printer settings which I can set are the same in both cases.
If anybody has an idea why there might be a difference, please let me know.

Related

Powershell in Batch file: Errors and Commands not executing

Below you can find the content of the two example text files I will use, example1.txt and obf_example1.txt. The latter one contains the string of example1.txt at the end of the file but has some obfuscated strings before.
example1.txt:
adasdkasdaksdasdkjlasdjasndjasd.
obf_example1.txt:
ŠxpÃÒ²Ø-Gêÿ ój"f>ïí H€À(ø4$/+#6Ni9Pvü¶ |CF CÀ¾ý~ª-°à9ÉOÿ V[o¦.E…-Š ƒ9Ú\žê*D´ß()^“£¹ìÅjXÑÍ¥â(¨µ×d'«P|I*èSººº&)Ø|̉ òÔ®¥Ô$LÁ:9ŠLá{¶nZÒبNÙÀØŒ‹0õ´Sék›áÇÉîÆbËF§BЄƒöZKaÒR ²°ÅšDn?+¶()IªP›$ÇEv©¡k€[ßè¨×q-Ëk!µTóPA²—: A ?ÉEEEGÐJúÌ©ÒWµHB¡aäXû|ÓË BPÁwr„Ûi¥åܺÈQ÷ORàSb,Šv¢D ,Žb’(2 öb¢wtKzíĦ#ï¯u©²Ù aîR隬ëÌTbà÷¥3ÄtSGì´R$)X Šù
'¹¨D³ÞeOK3!{·‹¦cäиNÅô:Na1žAÇ1ø8 &Fuôë %¸T¯_òMå†C"ý¤F ™º„Iµºí4Ü¡ˆc!ì•+3 ‰‹M K#JÁ«8¢bsL†!Ù“à­šn·öMå•Œ&ýèvÀ}¨?¦hùÊò(É#Žf~5‰‘qØçþƒ‰Å²ÓÖÊJU•âNWÁ«L¼Y”$G¢ßè&§ÖÉØŒS‘WàË„°SØW Ð¨´_è%‚Å¢ø.ãÃð”#X^þ*1þ‚q85¡lÒ‚Ò>‘¸ÿ £ôQôz#ø¤ÎõÚªï|Xö%;åÍËûGú+îUƒö³‰›p U±Ò ðtÜGÜÿ  ð,åXÿ k8È I”ÿ “½¿Ð`¨u5=SÓqyFÈ É8ôã¨ð£è6’H#lÄI10‚Ö§ÑdµÖ?t¡]D†9Zj,¥EɺÜEq¤#,ìn—¢º‚´€bc·ú¨Lû£ÿ Ó×ÿÙ||adasdkasdaksdasdkjlasdjasndjasd.
When I ran the following powershell command for example.txt in a batch file, it works and I get the output of example.txt:
#echo off
for /f "delims=" %%a in ('powershell Get-Content .\example.txt') do set _output=%%a
echo %_output%
adasdkasdaksdasdkjlasdjasndjasd
Good so far.
However, when I ran the above powershell command for obf_example1.txt, it does not work and I get the following error message:
'¹¨D³ÃzeOK3!{·â?¹Â¦cäÃ?Â?¸Â?NÃ.ô:Na1žAÃ╬1ø8
The command "FuôëÂ" is either misspelled or could not be found.
The command "ýèvÃ?}¨?¦hùÃSÂ?ò" is either misspelled or could not be found.
Why? Never mind I thought: As I am only interested in the last n characters both in example1.txt and obf_example1.txt accordingly, my idea was to extract the last n characters and check if I can see the output of obf_example1.txt then. To check if my idea works, I run the following command for example1.txt to get the last 4 characters as an example:
#echo off
for /f "delims=" %%a in ('powershell $a=Get-Content .\example.txt; $a.substring^(0,$a.length-4^)') do set _output=%%a
echo.%_output%
It doesn't show me anything though. %_output% seems to be empty. How to fix that? And will the fixed version work for obf_example1.txt as well so that I get an output there instead of the above error message?
Apparently, the piece of text you are after is behind the ||.
With PowerShell you can easily get that by using
((Get-Content 'D:\Test\obf_example1.txt' -Raw) -split '\|\|')[-1]
Returns
adasdkasdaksdasdkjlasdjasndjasd
Isn't htis what you want?
You could try reading the last 4 bytes, if you really are taking text characters from what is clearly not a text file. (My guess is that it is text hidden inside a binary file, probably a graphic file).
#For /F Delims^=^ EOL^= %%G In (
'%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoP^
"$f=[IO.File]::OpenRead('C:\Users\Ferit\Desktop\obf_example1.txt');"^
"$f.Seek(-4,[System.IO.SeekOrigin]::End)|Out-Null;$buffer=new-object Byte[] 4;"^
"$f.Read($buffer,0,4)|Out-Null;$f.Close();"^
"[System.Text.Encoding]::UTF8.GetString($buffer)"')Do #Set "_output=%%G"
#Set _output 2>NUL&&Pause
Don't forget to modify the text file path, (on line 3), and the three instances of 4 if you want more or less bytes. The last line is included just to show you the output, (you would obviously replace that with your own code).
The following works for me to get the "clear-text" part after || (from your example):
for /f "delims=" %%a in (.\obf_example1.txt) do set "_output=%%a"
set _output
echo testing last 10: %_output:~-10%
set "_output=%_output:*||=%"
set _output
echo %_output%
(it might not work with different encodings of the text file)
(Consider Powershell - cmd has a limit on line length and can easily be overwhelmed)

Assist with batch file that searches and xcopy hidden file to specific dir

It's annoying to manually always search in the CMD and xcopy the hidden file, can someone whos good in scipting help me out?
I use these 2 commands:
Firstly i open CMD in the FOLDER2 and entering this command to find the hidden file in the hidden random sub dir:
dir /s /b | find "robotknow"
(robotknow is not the fullname of the file, only part of it.)
And then when it find the hidden file within the random made subdir i copy the whole path including the whole filename with the ending.
Xcopy /h *The whole path including the filename and ending* C:\hello
My folders:
$sourceDir = 'C:\Users\USER\AppData\Local\Packages\FOLDER1\FOLDER2'
$targetDir = 'C:\hello'
So i wish to create a batch that could search that string "robotknow" and copy the fullname of the file to my tagetdir.
Is it possible?
Im trying to learn commands but batching is harder, if i was unclear on anything please ask me thank you!
Edit:
I found few commands that could be useful but I dont know how to use them so that it works.
$searchStrings = For it to search after the string above i mentioned: "robotknow"
And
Copy-Item $_.FullName $targetpath
An example would be:
The filename has this in it's name "robotknow" and i want to copy it.
Copy the file im searching after to copy thats within the sub folder of the FOLDER2 which is an hidden random folder that i cannot se:
%LocalAppData%\Packages\FOLDER1\FOLDER2\THE-hidden-RANDOM-made-sub-DIR.
Copy it to it's final directory c:\hello
The final directory, simply just: c:\hello.
By hidden i mean that i cannot see in file explorer, windows GUI and neither if i put this simple command in CMD dir to show the hidden random folder where the file is located in, they are not showing.
The file only appears in CMD if i enter this command dir /s /b | find "robotknow" when im in the FOLDER2.
Only after that i can se the hidden random made dir/folder and the full hidden path to it (the file).
I suggest following batch file code for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=%LocalAppData%\Packages\FOLDER1\FOLDER2"
set "TargetFolder=C:\hello"
for /F "delims=" %%I in ('dir "%SourceFolder%\*robotknow*" /A-D /B /S 2^>nul') do %SystemRoot%\System32\xcopy.exe "%%~dpI*" "%TargetFolder%\" /C /E /H /K /Q /R /Y >nul
endlocal
The command FOR with option /F starts a separate command process with cmd.exe /C (more precisely %ComSpec% /C) in background to run the command line:
dir "C:\Users\{username}\AppData\Local\Packages\FOLDER1\FOLDER2\*robotknow*" /A-D /B /S 2>nul
DIR outputs to handle STDOUT of background command process
just the names of all files matching the wildcard pattern *robotknow* because of option /A-D (attribute not directory)
even on file having hidden attribute set because of using option /A and not excluding attribute hidden
in bare format because of option /B
with full qualified path because of option /S
found in specified directory or any subdirectory also because of option /S.
It is possible that DIR does not find any file system entry matching these criteria in which case it outputs an error message to handle STDERR. This error message is suppressed by redirecting it to device NUL.
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
FOR with option /F captures all lines output to handle STDOUT of started command process and processes them line by line after started cmd.exe terminated itself.
FOR ignores empty lines which do not occur here. FOR ignores by default also all lines starting with a semicolon because of eol=; is the default for end of line character option. But a full qualified file name consisting of full file path, file name and file extension cannot start with ; and so default end of line option can be kept in this case. FOR splits up the lines by default into substrings with using normal space and horizontal tab character as string delimiters and assigns just first space/tab separated substring to specified loop variable. This line splitting behavior is not wanted here because of file path could contain a space character. For that reason option delims= is used to define an empty list of delimiters which disables the line splitting behavior.
So FOR assigns to specified and case-sensitive interpreted loop variable I the full qualified file name found and output by DIR and runs the command XCOPY.
XCOPY is executed with source being the full qualified path of found file referenced with %%~dpI always ending with a backslash concatenated with wildcard * and destination directory being specified target folder C:\hello.
The appended backslash at end of destination directory path makes it 100% clear for XCOPY that the destination is a directory and not a file which prevents the prompt if destination means a directory or a file. \ at end makes also usage of option /I unnecessary and XCOPY creates the entire destination directory structure if necessary.
The other XCOPY options are for really copying all files including files with hidden attribute set in directory containing the file matching the wildcard pattern *robotknow* with all subdirectories including empty subdirectories to destination directory with keeping attributes including read-only attribute.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
set /?
setlocal /?
xcopy /?
See also the list of predefined Windows Environment Variables.

xcopy one file to many computers in txt file

I am trying to copy one script file (DBFF.cmd) to many computers. I have created a computerlist.txt to list the names of each computer. On each line I have just the list of names ex. (win-ali) will someone please tell me where I may be going wrong?
for /F %%a in (computerlist.txt) do xcopy "\\tc\Install\Firefox_Deploy\DBFF.cmd" "\\%%a\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"
Without knowing what issues/errors you're encountering, it's going to be difficult to troubleshoot.
That being said, your example should work within a batch file. It will not work straight from the command line.
If you need it to work from the command line, change %%a to %a:
for /F %a in (computerlist.txt) do xcopy "\\tc\Install\Firefox_Deploy\DBFF.cmd" "\\%a\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"
Here's an old Microsoft post about the percent signs being stripped from batch files: https://support.microsoft.com/en-us/kb/75634

Batch Code to Skip Script if File is too Old

My Problem
As there are a ton of threads that address 'using a batch file to return file modify date' (or delete files older than, etc) - let me first specify my issue.
I'm looking to create a batch (not PowerShell, etc) that will return the last modify date of a specific file given UNC path and filename.
Code, Attempt 1
I've taken a peek at a few potential solutions on other threads, but I've run into a number of unique issues. The first and most obvious solution for this would be the "ForFiles" command in batch. For example:
set myPath=\\myUNCpath
set myFile=myFileName.csv
forfiles /p "%myPath%" /m %myFile% /c "GoTo OldFile" /d -6
Thus, if the file is older than I want -- jump to a specific section of my batch for that. However, this yields the error:
ERROR: UNC paths (\machine\share) are not supported.
However, this cmd won't work due to the use of UNC (which is critical as this batch is called by system's task scheduler). So it seems like the 'ForFiles' cmd is out.
Code, Attempt 2
I could go a more round about way of doing it, but simply retrieving the last modified date of the file (which in batch would return a string). I can truncate the string to the necessary date values, convert to a date, and then compare to current date. To do that, I've also looked into just using a for loop such as:
set myFile=\\myUNCpath\myFileName.csv
echo %myFile%
pause
FOR %%f IN (%myFile%) DO SET myFileDate=%%~tf
echo %myFileDate%
pause
Though my first debug echo provides the proper full file name, my second debug just returns ECHO is off., which tells me it's either not finding the file or the for loop isn't returning the file date. Not sure why.
I've also tried minor changes to this just to double check environmental variable syntax:
FOR %%f IN (%myFile%) DO SET myFileDate=%%~ta
Returns %ta
And finally:
FOR %%f IN (%myFile%) DO SET myFileDate=%~ta
Which without the extra '%', just crashes the batch.
I'm really at a loss at this point. So any tips or guidance would be greatly appreciated!
Using forfiles to a UNC path can be used using PushD
For just echoing the file older than x in UNC path, simply just use
PushD %myPath% &&(
forfiles -s -m %myFile% -d -6 -c "cmd /c echo /q #file
) & PopD
Here is one way how to use goto if file older than x found in UNC path using your examples.
if not exist "C:\temp" mkdir C:\temp
if not exist "C:\temp\test.txt" echo.>"c:\temp\test.txt"
break>"c:\temp\test.txt"
set myPath=\\myUNCpath
set myFile=myFileName.csv
PushD %myPath% &&(
forfiles -s -m %myFile% -d -6 -c "cmd /c echo /q #file >> c:\temp\test.txt"
) & PopD
for /f %%i in ("C:\temp\test.txt") do set size=%%~zi
if %size% gtr 0 goto next
:next
Huge thanks to both #Squashman and #MadsTheMan for the help. Luckily this batch finally is the piece of code that I can take to my boss to push switching over to at least using PowerShell!
Anyway, for those of you looking for the best way to get a UNC path file's modify date, here is what I've come up with. Not very different than other threads (and a thanks goes out to Squashman for spotting my missing " " in the for loop).
set myFile=\\myUNCpath\myFileName.ext
FOR %%f IN ("%myFile%") DO SET myFileDate=%%~tf
::And if you'd like to try to do long winded calculations you can further break the dates down via...
set fileMonth=%myFileDate:~0,2%
set fileDay=%myFileDate:~3,2%
set fileYear=%myFileDate:~6,4%
set currentDate=%date%
set currentMonth=%currentDate:~4,2%
set currentDay=%currentDate:~7,2%
set currentYear=%currentDate:~10,4%
The plan was to then convert the strings to integers, and then use a switch-case block to determine if the variance between dates was acceptable... blah blah blah.
Long story short - if you are limited to batch (and not creating secondary files -- such as a csv or the temp file suggested by MadsTheMan) you're going to have a really long script on your hands that still might have flaws (like leap year, etc unless you're adding even MORE code), when you could just make the comparison calculation using one line of code in other programs.

Issue with simple quote in bat file

I am trying to execute bat file containing a loop.
When executing a loop, the file execution is aborted.
I modified a little the command to understand what is the error and it seems I cannot put simple quote into the loop.
/f "tokens=1,2 delims==" %%i IN ("version=X.Z.W") do set VERSION=%%j -> success
/f "tokens=1,2 delims==" %%i IN ('version=X.Z.W') do set VERSION=%%j -> failure
It is annoying as version=X.Z.W should be returned by findstr /B /c:"%var%=" ..\..\file.properties
I tested on different desk, and this issue occurs only on my computer.
Do you know if there is any settings to modify?
I have the issue when typing the command directly into a command prompt.
Thanks a lot for your help.
If you are typing the above directly into a command prompt, it will fail because you have used %% instead of %. Windows CMD doesn't read %% as it does processing a batch file.
And the ' as opposed to " are read differently by CMD. ' is read as a command where " is read as a literal string.